bitkeeper revision 1.1159.17.17 (411b544doTQiJqVLC1XKbmd3zpnhzQ)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Thu, 12 Aug 2004 11:28:13 +0000 (11:28 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Thu, 12 Aug 2004 11:28:13 +0000 (11:28 +0000)
Use multicalls for context switch.

linux-2.6.7-xen-sparse/arch/xen/i386/kernel/process.c

index f67d8f8d91629ae8fb93079bafb2a304d47092f8..da60123dfd0e53de87c81e5bd2ca0f9646c6ec56 100644 (file)
@@ -46,6 +46,8 @@
 #include <asm/i387.h>
 #include <asm/irq.h>
 #include <asm/desc.h>
+#include <asm-xen/multicall.h>
+#include <asm/hypervisor-ifs/dom0_ops.h>
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
@@ -501,6 +503,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
        int cpu = smp_processor_id();
        struct tss_struct *tss = init_tss + cpu;
        unsigned long flags;
+       dom0_op_t op;
 
        local_irq_save(flags);
 
@@ -522,30 +525,51 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
                "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs" : : :
                "eax" );
 
-       flush_page_update_queue();
+       MULTICALL_flush_page_update_queue();
 
        /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
-       __unlazy_fpu(prev_p);
+       /*
+        * This is basically '__unlazy_fpu', except that we queue a
+        * multicall to indicate FPU task switch, rather than
+        * synchronously trapping to Xen.
+        */
+       if (prev_p->thread_info->status & TS_USEDFPU) {
+               save_init_fpu(prev_p);
+               queue_multicall0(__HYPERVISOR_fpu_taskswitch);
+       }
 
        /*
         * Reload esp0, LDT and the page table pointer:
+        * This is load_esp0(tss, next) with a multicall.
         */
-       load_esp0(tss, next);
+       tss->esp0 = next->esp0;
+       /* This can only happen when SEP is enabled, no need to test
+        * "SEP"arately */
+       if (unlikely(tss->ss1 != next->sysenter_cs)) {
+               tss->ss1 = next->sysenter_cs;
+               wrmsr(MSR_IA32_SYSENTER_CS, next->sysenter_cs, 0);
+       }
+       queue_multicall2(__HYPERVISOR_stack_switch, tss->ss0, tss->esp0);
 
        /*
         * Load the per-thread Thread-Local Storage descriptor.
+        * This is load_TLS(next, cpu) with multicalls.
         */
-       load_TLS(next, cpu);
+#define C(i) queue_multicall3(__HYPERVISOR_update_descriptor, virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), ((u32 *)&next->tls_array[i])[0], ((u32 *)&next->tls_array[i])[1])
+       C(0); C(1); C(2);
+#undef C
 
        if (start_info.flags & SIF_PRIVILEGED) {
-               dom0_op_t op;
                op.cmd           = DOM0_IOPL;
                op.u.iopl.domain = DOMID_SELF;
                op.u.iopl.iopl   = next->io_pl;
-               HYPERVISOR_dom0_op(&op);
+               queue_multicall1(__HYPERVISOR_dom0_op, (unsigned long)&op);
        }
 
+       /* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */
+       execute_multicall_list();
+
        local_irq_restore(flags);
 
        /*